﻿
Imports std
Imports storoomc

Public Module udclean

    Private Class arguments
        Public Const host As String = "host"
        Public Const port As String = "port"
        Public Const sleep As String = "sleep"

        Public Class defaultValue
            Public Shared ReadOnly sleep As Int64

            Shared Sub New()
                If isdebugmode() Then
                    sleep = 1000            '1 second
                Else
                    sleep = 5 * 60 * 1000   '5 minutes
                End If
            End Sub
        End Class
    End Class

    Private Sub writehelp()
        writeConsoleline("udclean -" + arguments.host + " <storoom host name or ip> -" _
                         + arguments.port + " <storoom port> -" _
                         + arguments.sleep + " <sleep ms between each round>")
    End Sub

    Private host As String = Nothing
    Private port As Int32 = 0
    Private sleeptime As Int64 = 0

    Private Function selectstoroom(ByRef h As String, ByRef p As Int32, ByRef retrytimes As Int64) As Boolean
        copy(h, host)
        copy(p, port)
        retrytimes = storoomc.talkTime.client2room.retrytimes

        Return True
    End Function

    Private Function iskey(ByVal key As String, ByVal value As String) As Boolean
        Return value.IndexOf(character.newline) = npos
    End Function

    Private Function isurl(ByVal key As String, ByVal value As String) As Boolean
        Return Not iskey(key, value)
    End Function

    Private Function urlnormalize(ByRef url As String) As Boolean
        If Not urlUtils.normalize(url) Then
            Return False
        Else
            'special treatment for storsync issue.
            assert(Not url Is Nothing, "url is nothing.")
            Dim index As Int64
            index = url.IndexOf(network.httpProtocol + network.protocolMark, 1)
            If index <> npos Then
                url = strleft(url, index)
            End If
            index = url.IndexOf(network.httpProtocol + network.protocolMark, 1)
            If index <> npos Then
                url = strleft(url, index)
            End If
            index = url.IndexOf(network.mailtoProtocol + network.protocolMark, 1)
            If index <> npos Then
                url = strleft(url, index)
            End If
            Return True
        End If
    End Function

    Private Sub handlekey(ByVal key As String, ByVal value As String)
        Dim url As String = Nothing
        copy(url, value)
        If urlnormalize(url) Then
            If Not strsame(url, value) Then
                raiseError("original url " + value + ", normalized to " + url)
                If Not storoom.modify(key, New bytes(encoding.utf8.GetBytes(url))) Then
                    raiseError("cannot modify " + key + " data to " + url, errorHandle.errorType.warning)
                End If
                If Not storoom.write(url, New bytes(encoding.utf8.GetBytes(key + character.newline))) Then
                    raiseError("cannot write to " + url + " data " + key, errorHandle.errorType.warning)
                End If
            End If
        Else
            raiseError("cannot normalize url " + url, errorHandle.errorType.warning)
        End If
    End Sub

    Private Sub handleurl(ByVal url As String, ByVal value As String)
        Dim originurl As String = Nothing
        copy(originurl, url)
        Dim temp As vector(Of String) = Nothing
        If urlnormalize(url) Then
            strsepar(value, character.newline, temp, True)
            Dim keys As [set](Of String) = Nothing
            If vector2set(temp, keys) Then
                assert(Not keys Is Nothing, "keys is nothing.")
                If Not strsame(originurl, url) OrElse temp.size() <> keys.size() Then
                    If Not storoom.delete(originurl) Then
                        raiseError("cannot delete origin url " + originurl, errorHandle.errorType.warning)
                    End If
                    Dim it As [set](Of String).iterator = Nothing
                    it = keys.begin()
                    While it <> keys.end()
                        If Not storoom.write(url, New bytes(encoding.utf8.GetBytes(+it + character.newline))) Then
                            raiseError("cannot write to " + url + " data " + +it, errorHandle.errorType.warning)
                        End If
                        it += 1
                    End While
                End If
            Else
                raiseError("caught " + value + " cannot be transform to keys set.", errorHandle.errorType.warning)
            End If
        Else
            raiseError("cannot normalize url " + url, errorHandle.errorType.warning)
        End If
    End Sub

    Public Sub main(ByVal iargs() As String)
        If ishelpArgument(iargs) Then
            writehelp()
            Return
        End If

        startmain()

        Dim args As map(Of String, vector(Of String)) = Nothing
        argmgr.parse(iargs, args, True)
        host = argmgr.firstvalue(args, arguments.host, True)
        port = argmgr.firstvalue(Of Int32)(args, arguments.port, True)
        sleeptime = argmgr.firstvalue(Of Int64)(args, arguments.port, True)

        storoom.initial(AddressOf selectstoroom)

        While Not consoleExtSignal()
            Dim keys As [set](Of String) = Nothing
            If Not storoom.list(keys) Then
                raiseError("cannot get list from storoom " + displayHostPort(host, port) + ", wait for next round." _
                           , errorHandle.errorType.warning)
                Continue While
            End If

            Dim it As [set](Of String).iterator = Nothing
            it = keys.begin()
            Dim buff As bytes = Nothing
            While it <> keys.end()
                If Not storoom.read(+it, buff) Then
                    raiseError("cannot read data from storoom " + displayHostPort(host, port) + ", key " + (+it) _
                               + ", ignore this key.", errorHandle.errorType.warning)
                    Continue While
                End If

                Dim value As String = Nothing
                value = encoding.utf8.GetString(+buff)
                Select Case True
                    Case isurl(+it, value)
                        If isdebugmode() Then
                            raiseError("handle key-value pair " + +it + " " _
                                       + strrplc(value, character.newline, character.blank) + " as url." _
                                       , errorHandle.errorType.application)
                        End If
                        handleurl(+it, value)
                    Case iskey(+it, value)
                        If isdebugmode() Then
                            raiseError("handle key-value pair " + +it + " " + value + " as key." _
                                       , errorHandle.errorType.application)
                        End If
                        handlekey(+it, value)
                    Case Else
                        raiseError("caught an key-value pair which is not a key and also not a url, " _
                                   + (+it) + ", " + value, errorHandle.errorType.warning)
                End Select
                it += 1
            End While

            sleep(sleeptime)
        End While

        finishmain()
    End Sub

End Module
